perm filename CURVES.MF[MF,DEK] blob sn#751800 filedate 1984-04-27 generic text, type T, neo UTF8
% this file was used in the lecture about curves

delimiters (); % ( and ) are like parens

def down=(0,-1) enddef;	% define four basic directions
def up=(0,1) enddef;
def right=(1,0) enddef;
def left=(-1,0) enddef;
def angle primary d = (cosd d, sind d) enddef; % and an arbitrary one

vardef z@#=(x@#,y@#) enddef;	% continue basic setup as in demo.mf

edges e;
e=nulledges;

def draw expr x = addto e contour x withweight 1 enddef;
def erase expr x = addto e contour x withweight -1 enddef;

openwindow 1 from (0,0) to (400,450) at (-100,200);

smoothing:=1; autorounding:=2;
hppp:=300/72.27; vppp:=hppp;
charcode:=96;

def next =	% this macro finishes one character and starts another:
 display e on 1;	% show what you've got
 shipout e;		% output it
 e:=nulledges;		% reset to blank
 charcode:=charcode+1;	% advance to the next character number
enddef;

tracingonline:=1; pausing:=1;
h=v=4;	% now we'll define the same points as last time, magnified fourfold

z1=(6h,0); z2=(0,8v); z3=(4h,11v); z4=(10h,8v); z5=(17h,9v); z6=(18h,2v);
z0=(9h,3v);
for n:=1 step 1 until 6: z[n]a-z0 = 2(z[n]-z0); endfor
% specifying directions at some of the points
% (last time METAFONT chose all directions by itself)

draw z1a{left}..z2a{up}..z3a..z4a..z5a..z6a..cycle;
erase z1{left}..z2{up}..z3..z4..z5..z6..cycle;
next;














% same, but with weirder directions

draw z1a{up}..z2a{left}..z3a..z4a..z5a..z6a..cycle;
erase z1{up}..z2{left}..z3..z4..z5..z6..cycle;
next;

show up,left;	% this shows that up=(0,1) and left=(-1,0)
		% [any direction is possible]














% here we force the curve to be a straight line between points 1 and 2

draw z1a{z2a-z1a}..z2a{z2a-z1a}..z3a..z4a..z5a..z6a..cycle;
erase z1{z2-z1}..z2{z2-z1}..z3..z4..z5..z6..cycle;
next;
% An `&' joins two independent pieces that touch

draw z1a..z2a..z3a..z4a & z4a..z5a..z6a..cycle;
erase z1..z2..z3..z4 & z4..z5..z6..cycle;
next;














% two other ways to get the same thing:

draw z1a..z2a..z3a..z4a..z4a..z5a..z6a..cycle;	% repeat a point twice
erase z1..z2..z3..z4{curl 1}..z5..z6..cycle;	% specify a "curl"
next;














% you can ask for more or less curl

draw z1a..z2a..z3a..z4a{curl 2}..z5a..z6a..cycle;
erase z1..z2..z3..z4{curl 0}& z4..z5..z6..cycle;
% that was "curl 0" at the left, "curl 1" (the default) at the right
next;
% here we put the curl at points 3 and 5 instead

draw z1a..z2a..z3a{curl 1}..z4a..z5a{curl 1}..z6a..cycle;
path p; p=z3..z4..z5;
erase z1..z2..z3 & p & z5..z6..cycle;
next;














% here we connect neighboring points by straight lines

erase z1..z2&z2..z3&z3..z4&z4..z5&z5..z6&z6..z1&cycle;
draw z1a..z2a&z2a..z3a&z3a..z4a&z4a..z5a&z5a..z6a&z6a..z1a&cycle;
next;

% notice that it's possible to erase before drawing!
% now here's a tricky way to change the meaning of ".."
% by calling it a "text parameter" to a macro:

def demochar(text ..)=
draw z1a..z2a..z3a..z4a..z5a..z6a..cycle;
erase z1..z2..z3..z4..z5..z6..cycle;
next;
enddef;

% you can vary the "tension" of the curve between points

demochar(..);
	% that's the default
	% (same as tension 1)




demochar(..tension 2..);
	% now pull tighter





demochar(..tension 1.2..);
	% now pull only a bit tighter





demochar(..tension 1000..);
	% now pull really hard





demochar(..tension 3/4..);
	% now push a bit
	% (3/4 is the minimum allowed)




demochar(..tension 1 and 2..);
	% tension is 1 when leaving a point
	% and 2 when coming into the next




demochar(..tension 2 and 1..);
	% here it's the other way 'round

path a.in, a.out;	% declare two variables of type "path"
a.out = % data taken from bitpad for a Baskerville "a"
(30.8154h,30.5538v)..(24.1231h,25.7692v)..(15.1231h,23.3692v)..(07.1692h,26.1692v)
..(03.6308h,33.6154v)..(10.0154h,44.2000v)..((23.0462h,51.3385v)..(27.2308h,53.2000v))
..(29.6615h,54.8000v)..((30.2000h,56.8923v)..(30.2154h,62.7846v))
..(29.7538h,66.2308v)..(27.5385h,69.8308v)..(21.7692h,71.4923v)..(17.2462h,70.8769v)
..(13.3538h,68.0462v)..((12.7538h,65.4000v)..(12.6462h,64.1692v))
..(11.3385h,61.2154v)..(09.3385h,60.5077v)..(06.9231h,61.4769v)..(05.6000h,64.2615v)
..(07.0154h,68.6923v)..(11.1538h,71.8923v)..(21.8000h,73.7846v)..(30.8154h,72.6000v)
..(38.0154h,67.7538v)..((39.2615h,60.7538v)..(39.4154h,36.1692v))
..(39.7231h,31.5538v)..(41.3231h,28.9077v)..(43.6462h,28.1231v)..(46.9385h,29.7385v)
..(48.1538h,32.2000v)
&(48.1538h,32.2000v)..(49.8462h,32.1077v)
&(49.8462h,32.1077v)..(47.4923h,26.3538v)..(41.2000h,23.5231v)..(35.0615h,25.4923v)
..(30.8154h,30.5538v) & cycle;

a.in =
((30.2154h,51.7692v)..(30.4308h,34.5385v))
..((28.0000h,31.0154v){curl 0}..(20.4769h,28.1385v)..(14.7077h,30.9077v)
   ..(13.2462h,36.2000v)..(17.1846h,44.3077v)..(30.2154h,51.7692v){curl 0}) & cycle;

draw a.out; erase a.in;
next;
% METAFONT actually computes two "control points" between every
% pair of given points on the curve.

tracingchoices:=1;	% you can see them by asking for this

% here's a path that leaves (0,0) at a 30 degree angle
% and comes in at a 60 degree angle:

show (0,0){angle 30}..(200,0){angle -60};

% (the incoming angle was said to be -60 because the path
% is actually traveling downward with respect to the
% horizon at the ending point)

% METAFONT shows the following in response to the above:

% Path at line 9, before choices:
% (0,0){0.86603,0.5}
%  ..(200,0){0.5,-0.86601}
%
% Path at line 9, after choices:
% (0,0)..controls (73.33493,42.33983) and (163.26099,63.63289)
%  ..(200,0)


% for comparison, here are two more cases:

show (0,0){angle 30}..(200,0);

% Path at line 28, before choices:
% (0,0){0.86603,0.5}
%  ..(200,0){curl 1}
% 
% Path at line 28, after choices:
% (0,0)..controls (61.88023,35.72647) and (138.11977,35.72647)
%  ..(200,0)

show (0,0){angle 30}..(200,0){curl 2};

% Path at line 38, before choices:
% (0,0){0.86603,0.5}
%  ..(200,0){curl 2}
% 
% Path at line 38, after choices:
% (0,0)..controls (63.67577,36.76312) and (142.7106,43.95956)
%  ..(200,0)


tracingchoices:=0; % now stop showing the choices of control points
% finally, we look at some of the ways a curve will vary
% when one of its angles is changing:

def tickmarks =
 draw (-5,0)..tension100..(0,0)..tension100..
	(0,-2)..tension100..(-5,-2)..tension100..cycle;
 draw (205,0)..tension100..(200,0)..tension100..
	(200,-2)..tension100..(205,-2)..tension100..cycle;
enddef;
def finish = % make it look like a loaf of bread baking
	(200,0)..(200,-100){down}..tension10..(0,-100){up}..(0,0) & cycle;
	tickmarks; next;
enddef;

draw (0,0){angle 30}..(200,0){angle -60} & finish;






draw (0,0){angle 60}..(200,0){angle -60} & finish;






draw (0,0){angle120}..(200,0){angle -60} & finish;






draw (0,0){angle-30}..(200,0){angle -60} & finish;






erase (0,0){angle 30}..(200,0){angle -60} &
      (200,0)..(200,-100){down}..tension10..(0,-100){up}..(0,0) & cycle;
draw (0,0){angle 60}..(200,0){angle -60} & finish;






end